package com.xccvt.aspect;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

import java.util.Arrays;

@Aspect
@Component
public class LoggingAspect {

    // 定义切入点：匹配UserService类中的所有公共方法
    @Pointcut("execution(public * com.xccvt.aspect.UserService.*(..))")
    public void serviceMethod() {}

    // 前置通知：在目标方法执行前执行
    @Before("serviceMethod()")
    public void logBefore(JoinPoint joinPoint) {
        System.out.println("[前置通知] 方法 " + joinPoint.getSignature().getName() + " 即将执行，参数: " + Arrays.toString(joinPoint.getArgs()));
        // 演示如何获取当前对象
        Object target = joinPoint.getTarget();
        Object[] args = joinPoint.getArgs();
        String methodName = joinPoint.getSignature().getName();
        
        System.out.println("  当前对象类型: " + target.getClass().getSimpleName());
        System.out.println("  当前对象完整类名: " + target.getClass().getName());
        System.out.println("  当前执行的方法: " + methodName);
        System.out.println("  方法参数: " + Arrays.toString(args));
        
        // 获取代理对象（如果使用了代理）
        Object thisObj = joinPoint.getThis();
        if (thisObj != target) {
            System.out.println("  代理对象: " + thisObj.getClass().getName());
        }
    }

    // 后置通知：在目标方法执行后执行（无论是否抛出异常）
    @After("serviceMethod()")
    public void logAfter(JoinPoint joinPoint) {
        System.out.println("[后置通知] 方法 " + joinPoint.getSignature().getName() + " 执行完毕");
    }

    // 返回通知：在目标方法成功执行后执行
    @AfterReturning(pointcut = "serviceMethod()", returning = "result")
    public void logAfterReturning(JoinPoint joinPoint, Object result) {
        System.out.println("[返回通知] 方法 " + joinPoint.getSignature().getName() + " 成功返回，结果: " + result);
    }

    // 异常通知：在目标方法抛出异常后执行
    @AfterThrowing(pointcut = "serviceMethod()", throwing = "exception")
    public void logAfterThrowing(JoinPoint joinPoint, Throwable exception) {
        System.out.println("[异常通知] 方法 " + joinPoint.getSignature().getName() + " 抛出异常: " + exception.getMessage());
    }

    // 环绕通知：环绕目标方法执行
    @Around("serviceMethod()")
    public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("[环绕通知 - 前] 执行 " + joinPoint.getSignature().getName() + " 方法");
        
        long startTime = System.currentTimeMillis();
        Object result;
        
        try {
            // 执行目标方法
            result = joinPoint.proceed();
        } catch (Throwable throwable) {
            System.out.println("[环绕通知 - 异常] 方法执行异常: " + throwable.getMessage());
            throw throwable;
        }
        
        long endTime = System.currentTimeMillis();
        System.out.println("[环绕通知 - 后] 方法执行完成，耗时: " + (endTime - startTime) + "ms");
        
        return result;
    }
}